package com.fanrui.code.chess.mahjong.round;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import com.fanrui.code.chess.mahjong.AbstractMahjongTable;
import com.fanrui.code.chess.mahjong.Mahjong;
import com.fanrui.code.chess.mahjong.MahjongGamer;
import com.fanrui.code.chess.mahjong.MahjongStandings.StandingsOperationType;
import com.fanrui.code.chess.mahjong.StandingsRound;
import com.fanrui.code.mahjong.util.MahjongCardUtil;
import com.fanrui.code.util.logger.Stdout;
import com.fanrui.proto.cmd.MahjongGroup;
import com.fanrui.proto.cmd.MahjongGroup.GroupType;
import com.fanrui.proto.cmd.NotifyCanOperationCard;
import com.fanrui.proto.cmd.Operation;
import com.fanrui.proto.cmd.ResPlayerOperation.Result;
import com.google.gson.annotations.Expose;

/**
 * 麻将摸牌回合
 * @author Administrator
 *
 */
public class MahjongTouchRound extends MahjongRound {

	private final static List<Operation> CANRESPONSE = Arrays.asList(Operation.ZIMO, Operation.SEND, Operation.GANG_A,
			Operation.GANG_B);
	
	@Expose
	private Mahjong touchCard;

	private Long gangId;
	
	public MahjongTouchRound(long currentId, AbstractMahjongTable<?> table, Long gangId) {
		super(currentId, CANRESPONSE, table);
		this.gangId = gangId;
	}
	
	public MahjongTouchRound(long currentId, AbstractMahjongTable<?> table, Mahjong touchCard, Long gangId) {
		this(currentId, table, gangId);
		this.touchCard = touchCard;
		MahjongGamer gamer = table.getGamerByPlayerID(currentId);
		if(gamer != null) {
			List<Operation> list  = gamer.canOperationCardListMySelf(touchCard);
			if(list != null && !list.isEmpty()) {
				NotifyCanOperationCard.Builder notify = NotifyCanOperationCard.newBuilder();
				for(Operation op : list) {
					notify.addOperation(op);
				}
				notify.setOperationMahjong(touchCard.toCardCmd());
				gamer.send(notify.build());
			}
		}
	}
	public Long getGangId() {
		return gangId;
	}

	public void setGangId(Long gangId) {
		this.gangId = gangId;
	}

	@Override
	public synchronized Result addResponse(MahjongOperationResponse response) {
		Result result = canOperationType(response);
		if (result != Result.Success) {
			return result;
		}
		MahjongGamer gamer = table.getGamerByPlayerID(response.getOperationId());
		Mahjong operationCard = response.getCard();
		if (gamer == null || operationCard == null) {
			Stdout.GET().info(getInfo() + " 没有找到玩家或者响应的牌无效 不能进行响应.响应内容:" + response);
			return Result.ParameterInvalid;
		}
		if (response.getType() == Operation.SEND) {
			if (MahjongCardUtil.getInstance().getCardNumFromHand1(operationCard, gamer.getHandCards())) {
				Stdout.GET().info(getInfo() + " 需要的手牌数量不足.响应内容:" + response); 
				return Result.NotHavaCard;
			}
			gamer.setGuoShouHuAuto(touchCard);
		}

		if (response.getType() == Operation.GANG_B || response.getType() == Operation.GANG_A) {// 杠碰牌
			int needNum = response.getType() == Operation.GANG_B ? 1 : 4;
			if (MahjongCardUtil.getInstance().getCardNumFromHand(operationCard, gamer.getHandCards()) < needNum) {
				Stdout.GET().info(getInfo() + " 手牌数量不足,响应失败.响应内容:" + response);
				return Result.NotHavaCard;
			}
			if (gamer.isHu()) {
				Stdout.GET().info(getInfo() + " 血流模式胡牌后不允许碰或杠牌,响应失败.响应内容:" + response);
				return Result.HuAndCandChange;
			}
			if (response.getType() == Operation.GANG_B) {
				boolean haveGroup = false;
				for (MahjongGroup group : gamer.getGroup()) {
					if (group.getType() == GroupType.PENG
							&& MahjongCardUtil.getInstance().toMahjongCard(group.getMjs(0)).cardEquals(operationCard)) {
						haveGroup = true;
						break;
					}
				}
				if (!haveGroup) {
					Stdout.GET().info(getInfo() + " 巴杠没有对应的碰牌,响应失败.响应内容:" + response);
					return Result.BaGangInvalid;
				}
			}
		}
		if (response.getType() == Operation.ZIMO) {
			if (!MahjongCardUtil.getInstance().checkHu(operationCard, gamer, table.getGameRules())) {
				Stdout.GET().info(getInfo() + "玩家的手牌达不成胡牌规则,响应失败.响应内容:" + response);
				return Result.CantHu;
			}
		} else if (MahjongCardUtil.getInstance().checkHu(touchCard, gamer, table.getGameRules())) {// 如果在能胡的情况下
			gamer.setGuoShouHuAuto(null);
		}
		// 判断是否能够加入到操作中
		addResponseToList(response);
		return result;
	}

	@Override
	public StandingsRound toStandingsRound() {
		if (touchCard != null) {
			return new StandingsRound(StandingsOperationType.Touch, currentId, null, touchCard);
		}
		return null;
	}

	@Override
	public Collection<Long> getCanResponseList() {
		return Arrays.asList(currentId);
	}

	@Override
	public Object doResponse() {
		if (playerResponse.isEmpty()) {
			return null;
		}
		if (isDoResponse) {
			return null;
		}
		isDoResponse = true;
		if (playerResponse.size() > 1) {
			System.out.println("有很多操作，请检查");
		}
		MahjongOperationResponse response = playerResponse.remove(0);
		Stdout.GET().info(response.toString());
		MahjongRound round;
		if (response.getType() == Operation.GANG_B && !table.getGameRules().getRoomConfig().getBaoHuPlayStyle().getQiang()) {
			round = new MahjongQiangGangHuRound(response, currentId, table);
		} else {
			// 找到一个合适的响应并执行
			round = RoundUtil.getInstance().createRound(this, response, table);
		}
		table.setCurrentRound(round);
		return null;
	}

	@Override
	public void before() {
		MahjongGamer gamer = table.getGamerByPlayerID(currentId);
		gamer.notifyResponse(MahjongOperationResponse.createTouchCardOperation(currentId, touchCard), waitTime);
		table.addRound(this);
		Stdout.GET().info(toString());
	}

	@Override
	public String toString() {
		MahjongGamer gamer = table.getGamerByPlayerID(currentId);
		return String.format("玩家%s摸牌 %s 摸牌后的手牌：%s", currentId, touchCard, gamer.getHandCards());
	}
	
	@Override
	public String getInfo() {
		return String.format("牌桌ID:%s --- 玩家:%s 摸牌回合", table.getID(), currentId);
	}

	@Override
	public MahjongOperationResponse getScoreResponse() {
		return toResponse();
	}

	@Override
	public boolean isAoutoNext() {
		return true;
	}
	
	private MahjongOperationResponse toResponse() {
		MahjongOperationResponse response = new MahjongOperationResponse();
		response.setCard(touchCard);
		response.setType(Operation.TOUCH);
		response.setOperationId(currentId);
		response.setTable(table);
		return response;
	}

}
